package grpc

import (
	"bytes"
	"context"
	filev1 "gitee.com/xiao_hange/go-admin-api/api/proto/gen/file/v1"
	"gitee.com/xiao_hange/go-admin-file/file/domain"
	"gitee.com/xiao_hange/go-admin-file/file/ioc/config"
	"gitee.com/xiao_hange/go-admin-file/file/service"
	"github.com/golang/protobuf/ptypes/timestamp"
	"go.opentelemetry.io/otel"
	"go.opentelemetry.io/otel/trace"
	"google.golang.org/grpc"
)

// FileServiceServer 这里只把 service 包装成一个 grpcx 接口 和 grpcx 相关的操作都在这里
type FileServiceServer struct {
	filev1.UnimplementedFileServiceServer
	scv    service.FileService
	sc     *config.ServerConfig
	tracer trace.Tracer
}

func NewFileServiceServer(scv service.FileService, sc *config.ServerConfig) *FileServiceServer {
	return &FileServiceServer{
		scv:    scv,
		sc:     sc,
		tracer: otel.Tracer("File服务-GRPC层"),
	}
}

func (f *FileServiceServer) Register(server *grpc.Server) {
	filev1.RegisterFileServiceServer(server, f)
}

func (f *FileServiceServer) UploadFile(ctx context.Context, req *filev1.UploadFileRequest) (*filev1.UploadFileResponse, error) {
	file, err := f.scv.UploadFile(ctx, domain.UploadFlieReq{
		OldName:  req.GetOldName(),
		FileType: req.GetFileType(),
		Size:     req.GetSize(),
		Reader:   bytes.NewReader(req.GetReader()),
	})
	if err != nil {
		return nil, err
	}
	return &filev1.UploadFileResponse{
		Val: file.Val,
		Url: file.Url,
	}, nil
}

func (f *FileServiceServer) DelFile(ctx context.Context, req *filev1.DelFileRequest) (*filev1.DelFileResponse, error) {
	err := f.scv.DelFile(ctx, req.GetId(), req.GetName())
	if err != nil {
		return nil, err
	}
	return &filev1.DelFileResponse{}, nil
}

func (f *FileServiceServer) GetLifeLst(ctx context.Context, req *filev1.GetLifeLstRequest) (*filev1.GetLifeLstResponse, error) {
	lsts, total, err := f.scv.GetLifeLst(ctx, int(req.GetPage()), int(req.GetLimit()), uint8(req.GetTypes()))
	if err != nil {
		return nil, err
	}
	result := make([]*filev1.File, len(lsts))
	for i, v := range lsts {
		result[i] = f.toDTO(v)
	}
	return &filev1.GetLifeLstResponse{
		File: result,
		Nt:   int64(total),
	}, nil
}

func (f *FileServiceServer) GetExportData(ctx context.Context, req *filev1.GetExportDataRequest) (*filev1.GetExportDataResponse, error) {
	//if f.sc.Port == 8091 {
	//	fmt.Println("模拟服务端异常选择其他服务")
	//	return &filev1.GetExportDataResponse{}, status.Errorf(codes.Unavailable, "模拟服务端异常")
	//}
	spanCtx := context.WithValue(ctx, "Enable", true)
	spanCtx, span := f.tracer.Start(spanCtx, "File服务-GRPC层: GetExportData")

	defer span.End()

	datas, total, err := f.scv.GetExportData(spanCtx, int(req.GetPage()), int(req.GetLimit()), int(req.GetExport()), req.GetMail())
	if err != nil {
		return nil, err
	}
	result := make([]*filev1.Data, len(datas))
	for i, v := range datas {
		result[i] = f.toDTOData(v)
	}
	return &filev1.GetExportDataResponse{
		Data: result,
		Nt:   int64(total),
	}, nil
}

func (f *FileServiceServer) EditName(ctx context.Context, req *filev1.EditNameRequest) (*filev1.EditNameResponse, error) {
	err := f.scv.EditName(ctx, req.GetId(), req.GetName())
	if err != nil {
		return nil, err
	}
	return &filev1.EditNameResponse{}, nil
}
func (f *FileServiceServer) toDTO(fi domain.File) *filev1.File {
	return &filev1.File{
		ID:         fi.ID,
		Type:       uint32(fi.Type),
		OldName:    fi.OldName,
		NewName:    fi.NewName,
		FileType:   fi.FileType,
		Size:       fi.Size,
		Image:      fi.Image,
		UpdateTime: &timestamp.Timestamp{Seconds: fi.UpdateTime.Unix(), Nanos: int32(fi.UpdateTime.Nanosecond())},
		CreateTime: &timestamp.Timestamp{Seconds: fi.CreateTime.Unix(), Nanos: int32(fi.CreateTime.Nanosecond())},
	}
}

func (f *FileServiceServer) toDTOData(d domain.Data) *filev1.Data {
	return &filev1.Data{
		Id:         d.ID,
		Title:      d.Title,
		Content:    d.Content,
		UpdateTime: &timestamp.Timestamp{Seconds: d.UpdateTime.Unix(), Nanos: int32(d.UpdateTime.Nanosecond())},
		CreateTime: &timestamp.Timestamp{Seconds: d.CreateTime.Unix(), Nanos: int32(d.CreateTime.Nanosecond())},
	}
}
